package com.ruoyi.system.service.impl;

import java.util.*;
import java.util.stream.Collectors;

import com.alibaba.fastjson2.JSON;
import com.ruoyi.common.core.domain.entity.SysDept;
import com.ruoyi.common.core.domain.model.LoginUser;
import com.ruoyi.common.exception.ServiceException;
import com.ruoyi.common.utils.DateUtils;
import com.ruoyi.system.domain.*;
import com.ruoyi.system.domain.req.DoseGetInfoReq;
import com.ruoyi.system.domain.vo.*;
import com.ruoyi.system.mapper.*;
import org.apache.commons.lang3.RandomStringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.ruoyi.system.service.IDoseMenuService;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;

/**
 * 每周菜单Service业务层处理
 *
 * @author ruoyi
 * @date 2025-09-20
 */
@Service
public class DoseMenuServiceImpl implements IDoseMenuService {
    @Resource
    private DoseMenuMapper doseMenuMapper;
    @Resource
    private DoseMenuDetailMapper doseMenuDetailMapper;
    @Resource
    private TypeMapper typeMapper;
    @Resource
    private MenuDetailMapper menuDetailMapper;
    @Resource
    private MealDetailMapper mealDetailMapper;
    @Resource
    private CateMapper cateMapper;
    @Resource
    private SpecMapper specMapper;
    @Resource
    private BrandMapper brandMapper;
    @Resource
    private SysDeptMapper sysDeptMapper;
    @Resource
    private MealMapper mealMapper;
    @Resource
    private MenuMapper menuMapper;
    @Resource
    private DoseMenuLogMapper doseMenuLogMapper;

    /**
     * 查询每周菜单
     *
     * @param id 每周菜单主键
     * @return 每周菜单
     */
    @Override
    public DoseMenuVO selectDoseMenuById(DoseGetInfoReq req, LoginUser loginUser) {
        if (req.getId() == null && req.getWeekStart() == null && req.getWeekEnd() == null) {
            throw new ServiceException("未选择报量单");
        }

        Map<Long, Cate> cateMap = cateMapper.selectCateList(new Cate()).stream().collect(Collectors.toMap(Cate::getId, t -> t));
        Map<Long, Type> typeMap = typeMapper.selectTypeList(new Type()).stream().collect(Collectors.toMap(Type::getId, t -> t));
        Map<Long, Spec> specMap = specMapper.selectSpecList(new Spec()).stream().collect(Collectors.toMap(Spec::getId, t -> t));
        Map<Long, Brand> brandMap = brandMapper.selectBrandList(new Brand()).stream().collect(Collectors.toMap(Brand::getId, t -> t));
        Map<Long, SysDept> schoolMap = sysDeptMapper.selectDeptList(new SysDept() {{
            setType(1);
        }}).stream().collect(Collectors.toMap(SysDept::getDeptId, t -> t));

        DoseMenuVO dose = new DoseMenuVO();
        DoseMenu dose_ = new DoseMenu();
        if (req.getId() != null) {
            dose_ = doseMenuMapper.selectDoseMenuById(req.getId());
        }
        if (req.getWeekStart() != null && !"".equals(req.getWeekStart())) {
            if (req.getWeekEnd() != null && !"".equals(req.getWeekEnd())) {
                List<DoseMenu> doses = doseMenuMapper.selectDoseMenuList(new DoseMenu() {{
                    setWeekStart(req.getWeekStart());
                    setWeekEnd(req.getWeekEnd());
                    setSchoolId(req.getSchoolId());
                }});
                if (!doses.isEmpty()) {
                    dose_ = doses.get(0);
                }
            }
        }

        if (dose_.getId() == null) {
            return new DoseMenuVO();
        }

        BeanUtils.copyProperties(dose_, dose);

        DoseMenuDetail doseDetail = new DoseMenuDetail();
        if (req.getId() == null) {
            doseDetail.setOrderId(dose_.getId());
        } else {
            doseDetail.setOrderId(req.getId());
        }

        doseDetail.setWeek(req.getWeek());

        final boolean[] mealFlag = {false};

        List<DoseMenuDetail> doseDetails = doseMenuDetailMapper.selectDoseMenuDetailList(doseDetail);
        doseDetails.forEach(item -> {
            if (cateMap.containsKey(item.getCateId())) {
                item.setCateName(cateMap.get(item.getCateId()).getName());
            }
            if (typeMap.containsKey(item.getTypeId())) {
                item.setTypeName(typeMap.get(item.getTypeId()).getName());
            }
            if (specMap.containsKey(item.getSpecId())) {
                item.setSpecName(specMap.get(item.getSpecId()).getName());
            }
            if (brandMap.containsKey(item.getBrandId())) {
                item.setBrandName(brandMap.get(item.getBrandId()).getName());
            }
            if (schoolMap.containsKey(item.getSchoolId())) {
                item.setSchoolName(schoolMap.get(item.getSchoolId()).getDeptName());
            }
            //是否是套餐
            if (item.getType() == 0) {
                mealFlag[0] = true;
            }
        });

        List<DoseMenuDetail_VO> details = new ArrayList<>(10);

        //根据日期分组
        TreeMap<String, List<DoseMenuDetail>> doseDetail_map = doseDetails.stream().collect(Collectors.groupingBy(DoseMenuDetail::getWeek, TreeMap::new, Collectors.toList()));


        doseDetail_map.forEach((key, value) -> {
            DoseMenuDetail_VO vo = new DoseMenuDetail_VO();
            vo.setWeek(key);
            List<DoseMenuDetail> doseDetail_morning = value.stream().filter(item -> "早餐".equals(item.getTime())).collect(Collectors.toList());
            List<DoseMenuDetail> doseDetail_noon = value.stream().filter(item -> "午餐".equals(item.getTime())).collect(Collectors.toList());
            List<DoseMenuDetail> doseDetail_evening = value.stream().filter(item -> "晚餐".equals(item.getTime())).collect(Collectors.toList());
            List<DoseMenuDetail> doseDetail_single = value.stream().filter(item -> item.getMenuId() == null && item.getMealId() == null).collect(Collectors.toList());

            List<DoseMenuDetail_menuVO> menuVOList_morning = formatData(mealFlag, doseDetail_morning);
            List<DoseMenuDetail_menuVO> menuVOList_noon = formatData(mealFlag, doseDetail_noon);
            List<DoseMenuDetail_menuVO> menuVOList_evening = formatData(mealFlag, doseDetail_evening);

            vo.setDetails_single(doseDetail_single);
            vo.setDetails_evening(menuVOList_evening);
            vo.setDetails_morning(menuVOList_morning);
            vo.setDetails_noon(menuVOList_noon);
            details.add(vo);
        });

        dose.setDetails(details);


//        if (dose.getSchoolId() != null) {
//            SysDept sysDept = sysDeptMapper.selectDeptById(dose.getSchoolId());
//            if (sysDept != null) {
//                dose.setSchoolName(sysDept.getDeptName());
//            }
//        }

        dose.setConfirmFlag(getConfirmFlag(dose, loginUser));

        return dose;
    }

    private List<DoseMenuDetail_menuVO> formatData(boolean[] mealFlag, List<DoseMenuDetail> details) {
        List<DoseMenuDetail_menuVO> menuVOList = new ArrayList<>(10);
        //是套餐
        if (mealFlag[0]) {
            Map<Long, List<DoseMenuDetail>> map = details.stream().collect(Collectors.groupingBy(DoseMenuDetail::getMealId));
            map.forEach((key_, value_) -> {
                DoseMenuDetail_menuVO menuVO = new DoseMenuDetail_menuVO();
                menuVO.setType(0);
                menuVO.setId(key_);
                menuVO.setName(mealMapper.selectMealById(key_).getName());
                List<MealDetail> mealDetails = mealDetailMapper.selectMealDetailList(new MealDetail(key_));
                mealDetails.forEach(item -> {
                    item.setMenuName(menuMapper.selectMenuById(item.getMenuId()).getName());
                });
                menuVO.setMeals(mealDetails);
                menuVO.setNum(value_.get(0).getNum());
                menuVO.setRemark(value_.get(0).getRemark());
                menuVOList.add(menuVO);
            });
        }
        //是菜谱
        else {
            Map<Long, List<DoseMenuDetail>> map = details.stream().collect(Collectors.groupingBy(DoseMenuDetail::getMenuId));
            map.forEach((key_, value_) -> {
                DoseMenuDetail_menuVO menuVO = new DoseMenuDetail_menuVO();
                menuVO.setType(1);
                menuVO.setId(key_);
                menuVO.setName(menuMapper.selectMenuById(key_).getName());
                menuVO.setDetails(value_);
                menuVOList.add(menuVO);
            });
        }
        return menuVOList;
    }

    /**
     * 查询每周菜单列表
     *
     * @param doseMenu 每周菜单
     * @return 每周菜单
     */
    @Override
    public List<DoseMenu> selectDoseMenuList(DoseMenu doseMenu, LoginUser loginUser) {

        return doseMenuMapper.selectDoseMenuList(doseMenu).stream().map(item -> {
            item.setExpireFlag(0);
            if (item.getDeadLine() != null) {
                //已超过确认期限
                if (item.getDeadLine().getTime() <= System.currentTimeMillis()) {
                    item.setExpireFlag(1);
                }
            }
            //查询当前登陆人是否已经点过确认
            item.setConfirmFlag(getConfirmFlag(item, loginUser));
            return item;
        }).collect(Collectors.toList());
    }

    /**
     * 根据当前登录人查询是否确认过
     */
    private Integer getConfirmFlag(DoseMenu item, LoginUser loginUser) {
        List<DoseMenuLog> list = doseMenuLogMapper.selectDoseMenuLogList(new DoseMenuLog(item.getId(), loginUser.getUser().getUserId(), loginUser.getUser().getType()));
        //是否确认 0未确认 1确认
        if (list != null && !list.isEmpty()) {
            return 1;
        }
        return 0;
    }


    /**
     * 新增每周菜单
     *
     * @param req 每周菜单
     * @return 结果
     */
    @Override
    @Transactional
    public int insertDoseMenu(DoseMenu req) {
        int i = 0;
        req.setCreateTime(DateUtils.getNowDate());

        List<DoseMenu> doses = doseMenuMapper.selectDoseMenuList(new DoseMenu() {{
            setSchoolId(req.getSchoolId());
            setWeekStart(req.getWeekStart());
            setWeekEnd(req.getWeekEnd());
        }});
        DoseMenu dose = null;
        if (!doses.isEmpty()) {
            dose = doses.get(0);
            i = 1;
        } else {
            dose = req;
            dose.setId(Long.valueOf(DateUtils.dateTimeNow() + RandomStringUtils.random(4, false, true)));
            i = doseMenuMapper.insertDoseMenu(dose);
        }

        List<DoseMenuDetail> doseDetails_morning = new ArrayList<>(10);
        List<DoseMenuDetail> doseDetails_noon = new ArrayList<>(10);
        List<DoseMenuDetail> doseDetails_evening = new ArrayList<>(10);
        List<DoseMenuDetail> doseDetails_meal_morning = new ArrayList<>(10);
        List<DoseMenuDetail> doseDetails_meal_noon = new ArrayList<>(10);
        List<DoseMenuDetail> doseDetails_meal_evening = new ArrayList<>(10);
        List<DoseMenuDetail> doseDetail_single = new ArrayList<>(10);

        List<DoseMenuDetail> doseDetails_add = new ArrayList<>(10);

        if (req.getParams().get("doseDetails") != null) {
            List<DoseMenuDetail> doseDetails = JSON.parseArray(JSON.toJSONString(req.getParams().get("doseDetails")), DoseMenuDetail.class);
            doseDetails.forEach(item -> {
//                item.setSchoolId(req.getSchoolId());
                if (item.getMealId() != null && item.getMenuId() == null) {
                    if ("早餐".equals(item.getTime())) {
                        doseDetails_meal_morning.add(item);
                    } else if ("午餐".equals(item.getTime())) {
                        doseDetails_meal_noon.add(item);
                    } else if ("晚餐".equals(item.getTime())) {
                        doseDetails_meal_evening.add(item);
                    }
//                    doseDetails_meal.add(item);
                } else if (item.getMealId() == null && item.getMenuId() == null) {
                    doseDetail_single.add(item);
                } else {
                    if ("早餐".equals(item.getTime())) {
                        doseDetails_morning.add(item);
                    } else if ("午餐".equals(item.getTime())) {
                        doseDetails_noon.add(item);
                    } else if ("晚餐".equals(item.getTime())) {
                        doseDetails_evening.add(item);
                    }
                }
            });
        }


        if (!doseDetails_morning.isEmpty()) {
            Map<String, Object> params = new HashMap<>(3);
            params.put("orderId", dose.getId());
            params.put("time", "早餐");
            params.put("week", req.getWeek());
            //删除原报量单的数据
            doseMenuDetailMapper.deleteDoseDetailByOrderId(params);
            formatDetailList(dose, req, doseDetails_morning, doseDetails_add);
        }
        if (!doseDetails_noon.isEmpty()) {
            Map<String, Object> params = new HashMap<>(3);
            params.put("orderId", dose.getId());
            params.put("time", "午餐");
            params.put("week", req.getWeek());
            doseMenuDetailMapper.deleteDoseDetailByOrderId(params);
            formatDetailList(dose, req, doseDetails_noon, doseDetails_add);
        }
        if (!doseDetails_evening.isEmpty()) {
            Map<String, Object> params = new HashMap<>(3);
            params.put("orderId", dose.getId());
            params.put("time", "晚餐");
            params.put("week", req.getWeek());
            doseMenuDetailMapper.deleteDoseDetailByOrderId(params);
            formatDetailList(dose, req, doseDetails_evening, doseDetails_add);
        }
        if (!doseDetail_single.isEmpty()) {
            Map<String, Object> params = new HashMap<>(3);
            params.put("orderId", dose.getId());
            params.put("week", req.getWeek());
            doseMenuDetailMapper.deleteDoseDetailByOrderId_single(params);
            formatDetailList(dose, req, doseDetail_single, doseDetails_add);
        }
        if (!doseDetails_meal_morning.isEmpty()) {
            Map<String, Object> params = new HashMap<>(3);
            params.put("orderId", dose.getId());
            params.put("week", req.getWeek());
            params.put("time", "早餐");
            doseMenuDetailMapper.deleteDoseDetailByOrderId_meal(params);
            formatDetailList_meal(dose, req, doseDetails_meal_morning, doseDetails_add);
        }
        if (!doseDetails_meal_noon.isEmpty()) {
            Map<String, Object> params = new HashMap<>(3);
            params.put("orderId", dose.getId());
            params.put("week", req.getWeek());
            params.put("time", "午餐");
            doseMenuDetailMapper.deleteDoseDetailByOrderId_meal(params);
            formatDetailList_meal(dose, req, doseDetails_meal_noon, doseDetails_add);
        }
        if (!doseDetails_meal_evening.isEmpty()) {
            Map<String, Object> params = new HashMap<>(3);
            params.put("orderId", dose.getId());
            params.put("week", req.getWeek());
            params.put("time", "晚餐");
            doseMenuDetailMapper.deleteDoseDetailByOrderId_meal(params);
            formatDetailList_meal(dose, req, doseDetails_meal_evening, doseDetails_add);
        }

        if (!doseDetails_add.isEmpty()) {
            doseMenuDetailMapper.insertDoseDetailBatch(new HashMap<String, Object>() {{
                put("doseDetails", doseDetails_add);
            }});
        }

        //删除所有确认记录
        doseMenuLogMapper.deleteDoseMenuLogByDoseId(dose.getId());
        return i;
    }

    private void formatDetailList(DoseMenu dose, DoseMenu req, List<DoseMenuDetail> items, List<DoseMenuDetail> doseDetails_add) {
        for (DoseMenuDetail item : items) {
            item.setOrderId(dose.getId());
            item.setCreateTime(dose.getCreateTime());
            item.setWeek(req.getWeek());
            item.setWeekTag(req.getWeekTag());
            Type type = typeMapper.selectTypeById(item.getTypeId());
            if (type != null) {
                item.setCateId(type.getCateId());
            }
            item.setType(1);
            doseDetails_add.add(item);
        }
    }

    private void formatDetailList_meal(DoseMenu dose, DoseMenu req, List<DoseMenuDetail> doseDetails_meal, List<DoseMenuDetail> doseDetails_add) {
        for (DoseMenuDetail item : doseDetails_meal) {
            item.setOrderId(dose.getId());
            item.setCreateTime(dose.getCreateTime());
            item.setWeek(req.getWeek());
            item.setWeekTag(req.getWeekTag());
            List<MealDetail> mealDetails = mealDetailMapper.selectMealDetailList(new MealDetail() {{
                setMealId(item.getMealId());
            }});
            for (MealDetail item_in : mealDetails) {
                List<MenuDetail> menuDetails = menuDetailMapper.selectMenuDetailList(new MenuDetail() {{
                    setMenuId(item_in.getMenuId());
                }});
                for (MenuDetail item_in_in : menuDetails) {
                    DoseMenuDetail doseDetail = new DoseMenuDetail();
                    BeanUtils.copyProperties(item, doseDetail);
                    doseDetail.setTypeId(item_in_in.getTypeId());
                    doseDetail.setSpecId(item_in_in.getSpecId());
                    doseDetail.setBrandId(item_in_in.getBrandId());

                    Type type = typeMapper.selectTypeById(item_in_in.getTypeId());
                    if (type != null) {
                        doseDetail.setCateId(type.getCateId());
                    }
                    doseDetail.setUseNum(doseDetail.getNum());
                    doseDetail.setNum(item_in_in.getNum().multiply(doseDetail.getUseNum()));
                    doseDetail.setType(0);
                    doseDetails_add.add(doseDetail);
                }
            }
        }
    }

    /**
     * 修改每周菜单
     *
     * @param doseMenu 每周菜单
     * @return 结果
     */
    @Override
    public int updateDoseMenu(DoseMenu doseMenu) {
        doseMenu.setUpdateTime(DateUtils.getNowDate());
        return doseMenuMapper.updateDoseMenu(doseMenu);
    }

    /**
     * 批量删除每周菜单
     *
     * @param ids 需要删除的每周菜单主键
     * @return 结果
     */
    @Override
    public int deleteDoseMenuByIds(Long[] ids) {
        return doseMenuMapper.deleteDoseMenuByIds(ids);
    }

    /**
     * 删除每周菜单信息
     *
     * @param id 每周菜单主键
     * @return 结果
     */
    @Override
    public int deleteDoseMenuById(Long id) {
        return doseMenuMapper.deleteDoseMenuById(id);
    }
}
